﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp;

/// <summary>
/// 多线程: 线程的创建和管理、同步机制、异步编程以及并行和并发
/// - 实现多线程的方式: 包括使用Thread类、ThreadPool、Task以及async和await等异步编程技术
/// - 并行和并发: Task.Parallel.For、Task.Parallel.ForEach或Parallel.Invoke
/// - 确保线程安全机制: 包括lock关键字、Monitor类、Mutex等
///  * 确保线程安全: 可以确保在给定时间内只有一个线程可以访问被保护的代码块,确保当多个线程同时访问共享资源时，保持数据的一致性和完整性
/// * 1.同步锁（lock 关键字）：适用于同一进程内的线程同步，简单易用，性能较好。它通常用于保护进程内的资源。
/// * 2.互斥锁（Mutex）：适用于跨进程的线程同步，允许不同进程中的线程同步访问资源。它通常用于保护跨进程的共享资源或在不同应用程序之间同步访问。
/// * 并发集合类: ConcurrentBag<object> ConcurrentDictionary<TKey, TValue> (推荐)
/// * 并发队列（如BlockingCollection）
/// * Dictionary + Lock 分区集合锁 (不推荐)
/// * 锁的范围应该尽可能小，以减少线程等待的时间。
/// * 避免死锁，即确保线程总是以相同的顺序请求锁。
/// * 注意: 过度使用锁可能会导致性能问题，因为锁会阻止其他线程访问被保护的资源，从而可能降低程序的并发性能。
/// </summary>
internal class DemoThread
{
    //定时器： 「固定时间间隔」执行某个「任务」
    //1.System.Threading.Timer
    //2.System.Timers.Timer
    //3.System.Diagnostics.Stopwatch
    //3.System.Threading.Tasks.Task
    //3.System.Windows.Forms.Timer
    //4.System.Windows.Threading.DispatcherTimer
    public void TimerTest()
    {
        var timer = new Timer(o =>
        {
            Console.WriteLine("1");
        }, null, 0, 500);
    }

    public void StopwatchTest()
    {
        var stopwatch = new Stopwatch();
        var interval = TimeSpan.FromSeconds(2); // 2秒间隔
        
        while (true)
        {
            stopwatch.Restart();
            
            Console.WriteLine($"开始执行任务: {DateTime.Now}");
            
            // 模拟任务执行
            Thread.Sleep(1000); // 任务执行时间
            
            // 计算剩余等待时间
            stopwatch.Stop();
            var remainingTime = interval - stopwatch.Elapsed;
            
            if (remainingTime > TimeSpan.Zero)
            {
                Thread.Sleep(remainingTime);
            }
        }
    }
    
    //1、Thread.Sleep 是同步延迟，Task.Delay异步延迟。
    //2、Thread.Sleep 会阻塞线程，Task.Delay不会。
    //3、Thread.Sleep 不能取消，Task.Delay可以。
    //4. Task.Delay() 比 Thread.Sleep() 消耗更多的资源，但是Task.Delay()可用于为方法返回Task类型；或者根据CancellationToken取消标记动态取消等待
    //5. Task.Delay() 实质创建一个运行给定时间的任务， Thread.Sleep() 使当前线程休眠给定时间。
    static void Threading()
    {
        var thread = new Thread(() =>
        {
            for (var i = 0; i < 100; i++)
            {
                Console.WriteLine($"子线程ID：{Thread.CurrentThread.ManagedThreadId}------{i}");
                Thread.Sleep(1000);
            }
        });
        //thread.IsBackground = true; // 后台线程
        thread.Start();
        Console.WriteLine($"主线程ID：{Thread.CurrentThread.ManagedThreadId}");
        Console.WriteLine("主线程结束!");
    }

    public static void t()
    {
        var watchers = new AutoResetEvent[10];
        for (var i = 0; i < 10; i++)
        {
            var j = i;
            watchers[j] = new AutoResetEvent(false);
       
            //启动10个线程输出10个数字
            new Thread(() =>
            {
                Console.WriteLine(j);
                watchers[j].Set();     //线程执行完的时候通知
            }).Start();
        }

        WaitHandle.WaitAll(watchers);  //确保所有线程都执行完毕
    }
        
    //线程池 Pool: ObjectPool/ThreadPool/ArrayPool/ConcurrentBag
    public static void Queue()
    {
        
        // 设置最小和最大线程数
        var minWorkerThreads = 4;
        var minCompletionPortThreads = 4;
        var maxWorkerThreads = 25;
        var maxCompletionPortThreads = 25;

        ThreadPool.SetMinThreads(minWorkerThreads, minCompletionPortThreads);
        ThreadPool.SetMaxThreads(maxWorkerThreads, maxCompletionPortThreads);
        
        // 注意: 无需等待处理结果时使用,需要全部完成等待结果请使用Task Task.WhenAll(tasks)
        // 将100个任务排队到线程池中
        for (var i = 0; i < 100; i++)
        {
            // 将一个任务排队到线程池中
            ThreadPool.QueueUserWorkItem((state) =>
            {
                // 执行任务
                Console.WriteLine($"子线程ID：{Thread.CurrentThread.ManagedThreadId}");
            });
        }
        
        // ThreadPool.GetAvailableThreads(out int workerThreads, out int completionPortThreads)：获取线程池中可用的工作线程数和I/O完成端口线程数。
        
        Console.WriteLine($"主线程ID：{Thread.CurrentThread.ManagedThreadId}");
        Console.WriteLine("主线程结束!");
    }

    //Token
    static void Token()
    {
        var cancleToken = new CancellationTokenSource();
        var thread = new Thread(() =>
        {
            var token = cancleToken.Token;
            while (!token.IsCancellationRequested)
            {
                Thread.Sleep(1000);
                Console.WriteLine("测试取消令牌！");
            }
        });
        thread.Start();
        Console.WriteLine("开始下载");
        Thread.Sleep(5000);
        cancleToken.CancelAfter(3000);
        Console.WriteLine("下载完成");
    }

    // 子线程完成才执行主线程
    static void Join()
    {
        var thread = new Thread(() =>
        {
            int i = 0;
            while (i++ < 10)
            {
                Thread.Sleep(new Random().Next(100, 1000));
                Console.WriteLine("Join test");
            }
        });
        thread.Start();
        thread.Join();
        Console.WriteLine("文件下载完成");
        Console.WriteLine("退出主程序");
    }

    // 同上 不推荐
    static void IsAlive()
    {
        var thread = new Thread(() =>
        {
            var i = 0;
            while (i++ < 10)
            {
                Thread.Sleep(new Random().Next(100, 1000));
                Console.WriteLine("Join test");
            }
        });
        thread.Start();
        while (thread.IsAlive)
        {
            Thread.Sleep(100);
        }
        Console.WriteLine("文件下载完成");
        Console.WriteLine("退出主程序");
    }

    //资源竞争与线程锁
    static void Lock()
    {
        for (var i = 0; i < 10; i++)
        {
            var thread = new Thread(AddText);
            thread.Start();
        }
        Console.WriteLine("文件下载完成");
        Console.WriteLine("退出主程序");
    }

    static object lockObj = new object();

    static void AddText()
    {
        lock (lockObj)
        {

            File.AppendAllText(@"ThreadTest.txt", $"开始：{Thread.CurrentThread.ManagedThreadId}");
            Thread.Sleep(1000);
            File.AppendAllText(@"ThreadTest.txt", $"结束：{Thread.CurrentThread.ManagedThreadId}");
        }
    }

    // Task
    public void demo1 ()
    {
        //方式一
        var task1 = new Task(() => { Console.WriteLine("线程1"); });
        task1.Start();

        //方式二
        var task2 = Task.Run(() => { Console.WriteLine("线程1"); });

        //方式三
        var task3 = Task.Factory.StartNew(() => { Console.WriteLine("线程1"); });
    }

    //阻塞模式
    public void demo2 ()
    {
        // 方式一
        //使用Task对象的Wait()函数分别等待单个线程任务完成，这种方式跟Thread的Join没啥区别，不推荐使用。
        var task1 = new Task(() => { Console.WriteLine("线程1"); });
        var task2 = new Task(() => { Console.WriteLine("线程2"); });
        task1.Start();
        task2.Start();

        task1.Wait();
        task2.Wait();


        // 方式二
        Task.WaitAll(task1, task2);

        // 方式三
        Task.WaitAny(task1, task2);
    }

    // 异步创建当另一任务完成时可以执行的延续任务。也就是当调用对象的线程任务完成后，执行ContinueWith()中的任务
    public void demo3 ()
    {
        var task1 = Task.Run(Calculator1);
        var task2 = Task.Run(Calculator2);
        Task.WhenAll(task1, task2).ContinueWith((data) => { Calculator3(data.Result[0], data.Result[1]); });

        Console.WriteLine("主线程已经完成");
        Console.Read();

        int Calculator1()
        {
            Thread.Sleep(1000);
            return 1 * 1;
        }

        int Calculator2()
        {
            Thread.Sleep(1000);
            return 1 * 2;
        }

        void Calculator3(int a, int b)
        {
            Console.WriteLine(a * b);
        }
    }

    public void demo4()
    {
        var task1 = Task.Run(() =>
        {
            Thread.Sleep(1000);
        });
        task1.ContinueWith((data) => { Console.WriteLine("线程1的延续"); });

        Console.WriteLine("主线程已经完成");
        Console.Read();
    }

    //父子任务
    public void parentTask()
    {
        Task parentTask = new Task(() => {
            Task task1 = new Task(() => { Console.WriteLine("task1任务。。。。。。"); }, TaskCreationOptions.AttachedToParent);
            Task task2 = new Task(() => { Console.WriteLine("task2任务。。。。。。"); }, TaskCreationOptions.AttachedToParent);
            task1.Start();
            task2.Start();
        });
        parentTask.Start();
        parentTask.Wait();
        Console.WriteLine("这里是主线程");
        Console.Read();
    }

    //耗时任务
    public void time()
    {
        Task task = new Task(() => { Console.WriteLine("task1任务。。。。。。"); }, TaskCreationOptions.LongRunning);
        task.Start();
    }

    // 取消令牌
    public void Cancel()
    {
        var cst = new CancellationTokenSource();
        var task = Task.Run(() => {
            while (!cst.IsCancellationRequested)
            {
                Console.WriteLine("持续时间:" + DateTime.Now);
            }
        }, cst.Token);//这里第二个参数传入取消令牌
            
        //1.Task任务的取消和判断
        Thread.Sleep(2000);
        cst.Cancel(); //两秒后结束

        //2.Task任务延时取消
        cst.CancelAfter(2000); //两秒后结束

        // 3.Task任务取消回调
        cst.Token.Register(() => {
            Console.WriteLine("开始处理工作......");
            Thread.Sleep(2000);
            Console.WriteLine("处理工作完成......");
        });
        Thread.Sleep(2000);
        cst.Cancel(); //两秒后结束
    }

    //Task跨线程访问控件
    //private void Button_Click(object sender, RoutedEventArgs e)
    //{
    //    txt_Info.Text = "数据正在处理中......";
    //    txt_Info.Text = "数据正在处理中......";
    //    Task.Run(() =>
    //    {
    //        Thread.Sleep(5000);
    //    }).ContinueWith(t => {
    //        txt_Info.Text = "test";
    //    }, TaskScheduler.FromCurrentSynchronizationContext());
    //}

    // Task异常处理
    public void ex()
    {
        var task1 = Task.Run(() =>
        {
            throw new Exception("线程1的异常抛出");
        });
        var task2 = Task.Run(() =>
        {
            throw new Exception("线程2的异常抛出");
        });
        var task3 = Task.Run(() =>
        {
            throw new Exception("线程3的异常抛出");
        });

        try
        {
            task1.Wait();
            task2.Wait();
            task3.Wait();
        }
        catch (AggregateException ex)
        {
            foreach (var item in ex.InnerExceptions)
            {
                Console.WriteLine(item.Message);
            }
            //如果希望再将异常往外抛出，可以调用AggregateException的Handle函数
            //ex.Handle(p => false);
        }
        Console.Read();
    }
    
    public static void Delay()
    {
        Console.WriteLine("Mian方法第一次输出...");
        #region 第一种形式 
        var task_1 = Task.Run(async delegate
        {
            await Task.Delay(3000);
            Console.WriteLine("3秒后执行，方式一 输出语句...");
            return "异步执行result"; //可以得到一个返回值(int,bool,string都试了)
        });
        #endregion

        Console.WriteLine("Mian方法第二次输出，调用延时...");
        Console.WriteLine("task_1 的 Status:{0}, 结果: {1}",task_1.Status, task_1.Result);
        Console.WriteLine("第一种形式，延时结束...");

        #region 第二种形式
        Task task_2 = Task.Run(task_YS);
        //task_2.Wait();  //注释打开则等待task_2延时，注释掉则不等待
        #endregion

        Console.WriteLine("Mian方法最后一次输出，Main方法结束...");
        Console.ReadKey();
    }
    
    public static async Task task_YS()
    {
        await Task.Delay(5000);
        Console.WriteLine("5秒后执行，方式二 输出语句...");
    }
    
    public static async Task ExampleMethod()
    {
        Console.WriteLine("Before await");
        // 在新的进程中进行
        await Task.Run(() => 
        {
            Console.WriteLine("During await");
            Thread.Sleep(2000);  // 模拟耗时操作
            Console.WriteLine("After await");
        });
        Console.WriteLine("After task");
    }

    public static async Task demo()
    {
        var tasks = new List<Task>();

        for (var i = 0; i < 5; i++)
        {
            var taskId = i;
            // 启动异步任务
            var task = Task.Run(async () =>
            {
                Console.WriteLine($"Task {taskId} 开始执行");
                await Task.Delay(1000); // 模拟任务的耗时操作
                Console.WriteLine($"Task {taskId} 执行完成");
            });
            
            tasks.Add(task);
        }

        // 等待所有任务完成
        await Task.WhenAll(tasks);
    }
    
    //无论有多少个实例对象，lock都会确保在同一时刻只有一个线程可以访问该静态变量
    private static object _staticLock = new object();
    //每个对象实例可以有自己的锁，多个线程可以同时访问不同对象实例的非静态变量，但同一个对象实例中的不同线程必须同步其访问。注意:多实例，线程并发（加锁失败）
    private object _instanceLock = new object();
    public static int StaticCounter = 0;
    public int InstanceCounter = 0;
    
    public void IncrementStatic()
    {
        lock (_staticLock)
        {
            StaticCounter++;
            Console.WriteLine("Static" + DateTime.Now.Millisecond);
        }
    }
 
    public void IncrementInstance()
    {
        lock (_instanceLock)
        {
            InstanceCounter++;
            Console.WriteLine("Instance" + DateTime.Now.Millisecond);
        }
    }
    
    // 锁对象应该是私有的，以避免在代码的其他部分被意外锁定
    private readonly object _lockObject = new object();

    // lock 同步锁,内部实际上使用的是Monitor类来管理锁
    public void PerformCriticalSection(int id)
    {
        // lock 关键字在进入一个代码块之前获取锁，并在退出代码块时释放锁。
        lock (_lockObject)
        {
            Task.Delay(3000);
            // 临界区代码，一次只能被一个线程访问
            Console.WriteLine(id);
        }
    }
    
    // System.Threading.Mutex
    private readonly object _lockMonitor = new object();

    public void MonitorPerformCriticalSection()
    {
        // Monitor 类提供了更底层的同步机制，允许你手动请求和释放锁。
        Monitor.Enter(_lockMonitor);
        try
        {
            // 临界区代码
        }
        finally
        {
            Monitor.Exit(_lockMonitor);
        }
    }
    
    // System.Threading.Mutex
    private Mutex _mutex = new Mutex();

    public void MutexPerformCriticalSection()
    {
        // 等待获取互斥锁
        _mutex.WaitOne();
        //_mutex.WaitOne(TimeSpan.FromSeconds(5));
        try
        {
            // 临界区代码
        }
        finally
        {
            // 释放锁
            _mutex.ReleaseMutex();
        }
    }

    public void mutexDemo()
    {
        var mutex = new Mutex(false, "MyUniqueMutexIdentifier");
        bool hasHandle = false;
        try
        {
            hasHandle = mutex.WaitOne(TimeSpan.FromSeconds(5));
            if (hasHandle)
            {
                // 临界区代码，一次只有一个进程中的线程可以执行这里
            }
        }
        finally
        {
            if (hasHandle)
            {
                mutex.ReleaseMutex();
            }
        }
    }
    
    // System.Threading.SemaphoreSlim 更轻量级的同步原语，用于限制对资源的并发访问
    private readonly SemaphoreSlim _semaphore = new(1);

    public async Task PerformCriticalSectionAsync()
    {
        //异步请求锁
        await _semaphore.WaitAsync();
        try
        {
            // 临界区代码
        }
        finally
        {
            // 释放锁
            _semaphore.Release();
        }
    }
    
    // System.Threading.ReaderWriterLockSlim 属性 如 CurrentReadCount、WaitingReadCount、WaitingUpgradableReadCount 和 WaitingWriteCount，用于获取当前锁定的相关信息
    private static readonly ReaderWriterLockSlim _toolLock = new();

    // 读取资源
    private string Read()
    {
        try
        {
            _toolLock.EnterReadLock(); // 获取读取锁
            
            return null;
        }
        catch
        {
            // 异常处理
        }
        finally
        {
            _toolLock.ExitReadLock(); // 释放读取锁
        }
        return default;
    }

    //写入资源
    public void Write(int key, int value)
    {
        try
        {
            _toolLock.EnterUpgradeableReadLock();
            try
            {
                _toolLock.EnterWriteLock();
                // 执行写入操作
            }
            finally
            {
                _toolLock.ExitWriteLock();
            }
        }
        catch
        {
            // 异常处理
        }
        finally
        {
            _toolLock.ExitUpgradeableReadLock();
        }
    }
    
    //System.Threading.Interlocked: 用于在多线程环境中安全地执行对共享变量的简单操作，而无需使用显式的锁.原子操作是不可中断的操作，即一旦开始，就会一直执行到完成，中间不会被其他线程打断
    //Interlocked类的方法特别适用于读写简单的数据类型，如整数、长整数和引用类型。通过使用Interlocked类，可以避免由于线程切换或上下文切换导致的竞态条件，从而提高性能。
    
    private int _count = 0;
    public int Increment()
    {
        Interlocked.Increment(ref _count);
        return _count;
        //Interlocked.Increment(ref int location): 将指定位置的整数值原子地递增1。
        //Interlocked.Decrement(ref int location): 将指定位置的整数值原子地递减1。
        //Interlocked.Add(ref int location, int value): 将指定的值原子地加到指定位置的整数值上。
        //Interlocked.CompareExchange(ref int location, int value, int comparand): //比较指定位置的整数值与比较值。如果它们相等，则将该位置的值设置为新值。
        //Interlocked.Exchange(ref int location, int value);: 将指定位置的整数值设置为给定值，并返回原始值。
        //Interlocked.Read(ref int location): 原子地读取指定位置的整数值。
        //Interlocked.Write(ref int location, int value): 原子地将给定值写入指定位置的整数。
    }
    
    //并行计算库（Parallel Computing Library），它允许开发者轻松地利用多核处理器的能力来并行处理任务，从而显著提高程序的运行速度。
    //线程安全：确保你的代码是线程安全的，特别是当多个线程可能同时访问和修改共享数据时。
    //任务划分：合理地将任务划分为可以并行执行的部分，以充分利用多核处理器的能力。
    //资源竞争：避免过度的线程间资源竞争，这可能会导致性能下降。
    //异常处理：在并行代码中妥善处理异常，确保程序的稳定性和可靠性。
    //性能测试：在使用并行处理之前和之后进行性能测试，以确保并行化确实带来了性能提升。

    // 1.并行循环
    public void ParallelDemo1()
    {
        int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        var squares = new int[numbers.Length];

        // 使用Parallel.For并行计算平方
        Parallel.For(0, numbers.Length, i =>
        {
            squares[i] = numbers[i] * numbers[i];
        });

        // 打印结果
        for (var i = 0; i < squares.Length; i++)
        {
            Console.WriteLine($"The square of {numbers[i]} is {squares[i]}");
        }
    }

    // 2.并行迭代
    public void ParallelDemo2()
    {
        // 使用ConcurrentBag来收集结果，因为它是线程安全的
        var results = new ConcurrentBag<int>();
        
        var data = new ConcurrentBag<string> { "apple", "banana", "cherry", "date", "elderberry" };
        // 使用Parallel.ForEach并行打印字符串长度
        Parallel.ForEach(data, item =>
        {
            // 模拟处理过程
            Console.WriteLine($"The length of '{item}' is {item.Length}");
            // 将结果添加到ConcurrentBag中
            results.Add(item.Length);
        });
        
        // 输出所有结果
        foreach (var result in results)
        {
            Console.WriteLine(result);
        }
    }

    // 并行迭代(异步)
    public async Task ParallelDemo22()
    {
        // // 等待所有任务完成并收集结果
        // var tasks = new List<Task>();
        // var data = Enumerable.Range(1, 10).ToList();
        //
        // try
        // {
        //     // 异步：这样做可能会导致线程池中的线程被过度使用，因为Parallel.ForEach会尝试并行化任务，而每个任务本身又是异步的
        //     Parallel.ForEach(data, async item =>
        //     {
        //         // 启动异步任务
        //         var task = Task.Run(async () =>
        //         {
        //             try
        //             {
        //                 // 模拟异步操作
        //                 await Task.Delay(1000);
        //                 Console.WriteLine($"Processed item {item}");
        //             }
        //             catch (Exception ex)
        //             {
        //                 // 处理异常
        //                 Console.WriteLine($"Error processing item {item}: {ex.Message}");
        //             }
        //         });
        //
        //         // 将任务添加到列表中以便后续等待
        //         tasks.Add(task);
        //     });
        //
        //     // 等待所有任务完成
        //     await Task.WhenAll(tasks);
        // }
        // catch (AggregateException ex)
        // {
        //     // 处理 Parallel.ForEach 中的异常
        //     foreach (var innerEx in ex.InnerExceptions)
        //     {
        //         Console.WriteLine($"Aggregate exception: {innerEx.Message}");
        //     }
        // }
        return;
        
        // 假设我们有一列数据需要处理
        var data = Enumerable.Range(1, 100).ToList();

        // 使用List<Task<T>>来收集任务
        var tasks = new List<Task<int>>();
        foreach (var item in data)
        {
            // 启动异步任务，并将任务添加到tasks列表中
            tasks.Add(await Task.Run(async () =>
            {
                // 模拟异步处理过程，这里我们简单地将数据项乘以2并返回一个Task<int>
                await Task.Delay(100); // 模拟异步等待
                return ProcessDataAsync(item);
            }));
        }

        // 等待所有任务完成，并收集结果
        var results = await Task.WhenAll(tasks);

        // 输出所有结果
        foreach (var result in results)
        {
            Console.WriteLine(result);
        }
    }
    
    // 模拟的异步数据处理函数
    static async Task<int> ProcessDataAsync(int data)
    {
        // 这里可以添加实际的异步处理逻辑
        await Task.Delay(50); // 模拟异步操作
        return data * 2;
    }
    
    // 3.并行执行一组委托
    public void ParallelDemo3()
    {
        // 使用Parallel.Invoke并行执行三个方法
        Parallel.Invoke(
            Method1,
            Method2,
            Method3
        );
    }

    static void Method1()
    {
        Console.WriteLine("Executing Method1 on thread: " + Thread.CurrentThread.ManagedThreadId);
        // 模拟一些工作...
        Thread.Sleep(1000); // 不要在生产代码中使用Thread.Sleep!
    }

    static void Method2()
    {
        Console.WriteLine("Executing Method2 on thread: " + Thread.CurrentThread.ManagedThreadId);
        // 模拟一些工作...
        Thread.Sleep(1500); // 不要在生产代码中使用Thread.Sleep!
    }

    static void Method3()
    {
        Console.WriteLine("Executing Method3 on thread: " + Thread.CurrentThread.ManagedThreadId);
        // 模拟一些工作...
        Thread.Sleep(2000); // 不要在生产代码中使用Thread.Sleep!
    }

    public static async void Block1()
    {
        var blocks = new List<DataBlock>();
        for (var i = 0; i < 100000; i++)
        {
            blocks.Add(new DataBlock
            {
                Id = i,
                Name = $"Name{i}"
            });
        }
            
        // 任务开始时间
        var sw = Stopwatch.StartNew();
        foreach (var block in blocks)
        {
            block.Age = block.Id + 1;
        }
        JsonSerializer.Serialize(blocks);
        sw.Stop();
        Console.WriteLine("1: " + sw.ElapsedMilliseconds);
    }
    
    public class DataBlock
    {
        public int Id { get; set; }
        // 其他数据块相关属性
        
        public required string Name { get; set; }
        
        public int Age { get; set; }
    }
}